﻿package 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.display.BlendMode;
	import flash.ui.Keyboard;
	import flash.display.StageQuality;
	import flash.utils.Timer;
	import flash.utils.clearTimeout;
	import flash.utils.setTimeout;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	
	import alternativa.engine3d.controllers.CameraController;
	import alternativa.engine3d.controllers.WalkController;
	import alternativa.engine3d.core.Camera3D;
	import alternativa.engine3d.core.Object3D;
	import alternativa.engine3d.core.Scene3D;
	import alternativa.engine3d.display.View;
	import alternativa.engine3d.materials.TextureMaterial;
	import alternativa.engine3d.materials.WireMaterial;
	import alternativa.engine3d.materials.FillMaterial;
	import alternativa.engine3d.events.MouseEvent3D;
	import alternativa.engine3d.core.Sprite3D;
	import alternativa.types.Point3D;
	import alternativa.types.Texture;
	import alternativa.utils.FPS;
	import alternativa.utils.MathUtils;
	
	import classes.showModel3D;
	import classes.showAxis3D;
	import classes.showFloor3D;
	import classes.showTextHelp;
	import classes.showMusicSelection;
	import classes.uam3Dmesh;
	import classes.skyBox;
	import classes.ProgressWindow;
	
	[SWF(backgroundColor = "#000000", frameRate = "100")]

	public class Main extends Sprite 
	{	
		private var scene:Scene3D;
		private var view:View;
		private var camera:Camera3D;
		private var cameraController:CameraController;
		private var controller:WalkController;
		private var qualityTimerId:int = -1; 
		private var qualitySwitchTime:uint = 500;
		private var makeSkyBox:skyBox = makeSkyBox = new skyBox ();
		private var startPlatform:showFloor3D;
		private var instModel3D:showModel3D = new showModel3D("model/laberinto_25_2.3ds", 1);
		
		//private var uam3dText:uam3Dmesh = new uam3Dmesh();
		private var spHelpInstructions:showTextHelp = new showTextHelp();
		private var spMusicSelection:showMusicSelection =  new showMusicSelection();
		
		// Resources loading sequence
		private var loadingSequence:Array =[instModel3D, makeSkyBox, spMusicSelection, spHelpInstructions, startPlatform];
		private var loadingCounter:int = -1;
		private var progressWindow:ProgressWindow;
		
		public function Main():void
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		public function init(e:Event = null):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			
			
			initScene();
			initListeners();
			
			
			onResize(null);
		}
		
		private function initScene():void 
		{	
			progressWindow = new ProgressWindow("Loading resource", 200);
			progressWindow.y = 10;
			progressWindow.x = 300;
			stage.addChild(progressWindow);
			
			// Sequence of the objects, for which textures are loading

			// Start textures loading
			loadNextResource();
			
			
			// Creating scene
			scene = new Scene3D();
			scene.root = new Object3D();
			
			// Adding camera and a view
			camera = new Camera3D();
			scene.root.addChild(camera);
			
			view = new View();
			view.interactive = true;
			view.camera = camera;
			addChild(view);
			
			
			// Load 3D floor
			var floor3D:showFloor3D = new showFloor3D(2000, 2000);
			scene.root.addChild(floor3D);
			startPlatform = new showFloor3D(100, 100);
			startPlatform.z = 500;
			scene.root.addChild(startPlatform);
			
			// Help instructions 
			spHelpInstructions.sp.x = stage.stageWidth / 2 - spHelpInstructions.sp.width / 2;
			spHelpInstructions.sp.y = stage.stageHeight / 2 - spHelpInstructions.sp.height / 2;
			addChild(spHelpInstructions);
			
			// UAM 3d text
			//uam3dText.cloneMaterialToAllSurfaces(new FillMaterial(Math.random()*0xFFFFFF, 0.5, BlendMode.NORMAL, 1));
			//uam3dText.z = 500;
			//uam3dText.x = 200;
			//uam3dText.rotationX = MathUtils.DEG90;
			//uam3dText.rotationZ = MathUtils.DEG90 * 3;
			//scene.root.addChild(uam3dText);
			
			// skyBox (without embed)
			var makeSkyBox:skyBox = makeSkyBox = new skyBox (); 
			scene.root.addChild(makeSkyBox);
			
			// show public 3D model
			scene.root.addChild(instModel3D);
			
			// Show 3D Axis
			var axis3D:showAxis3D = new showAxis3D(500, 500, 500);
			scene.root.addChild(axis3D);
			
			// FPS counter init
			FPS.init(stage);
			
			controller=new WalkController(stage);
			controller.object = camera;
			controller.onStartMoving = setLowQuality;
			controller.onStopMoving = startHighQualityTimer;
			controller.setDefaultBindings();
			controller.mouseEnabled = true;
			controller.checkCollisions = true;
			controller.gravity = 500;
			controller.jumpSpeed = 200;
			controller.flyMode = false;
			controller.speed = 100;
			controller.collider.radiusX = 5;
			controller.collider.radiusY = 5;
			controller.collider.radiusZ = 5;
			controller.objectZPosition = 1.2;
			//controller.onStartMoving
			//controller.coords = new Point3D(200, 200, 500); // start Point
			controller.coords = new Point3D(0, 0, startPlatform.z + 200); // start Point
			controller.lookAt(new Point3D(200, 200, 500)); // lookAt start Point 
			
			// Music selection
			spMusicSelection.x = 5;
			spMusicSelection.y = stage.stageHeight - spMusicSelection.height;
			addChild(spMusicSelection);
		}
		
		private function onEnterFrame(e:Event):void 
		{
			controller.processInput();
			scene.calculate();
		}
		
		private function initListeners():void 
		{
			stage.addEventListener(Event.RESIZE, onResize);
			stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
			stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
		}
		
		private function onResize(e:Event):void 
		{
			view.width = stage.stageWidth;
			view.height = stage.stageHeight;
			
			spMusicSelection.y =  stage.stageHeight - spMusicSelection.height;
			
			spHelpInstructions.sp.x = stage.stageWidth / 2 - spHelpInstructions.sp.width / 2;
			spHelpInstructions.sp.y = stage.stageHeight / 2 - spHelpInstructions.sp.height / 2;
			
			spHelpInstructions.helpButton.x = -spHelpInstructions.helpButton.parent.x + 3;
			spHelpInstructions.helpButton.y = -spHelpInstructions.helpButton.parent.y + 3;
			
			progressWindow.x = (stage.stageWidth - progressWindow.width) >> 1;
		}
		
		private function onKeyUp(e:KeyboardEvent):void 
		{
			switch(e.keyCode) 
			{
				case Keyboard.ENTER: // return to the start
					controller.coords = new Point3D(0, 0, startPlatform.z + 200); // start Point
					controller.lookAt(new Point3D(200, 200, 500)); // lookAt start Point 
				break;
				case Keyboard.F1:
					controller.coords = new Point3D(300, 300, startPlatform.z + 200); // start Point
					controller.lookAt(new Point3D(200, 200, 500)); // lookAt start Point 
				break;
				case Keyboard.F2:
					controller.coords = new Point3D(-300, 300, startPlatform.z + 200); // start Point
					controller.lookAt(new Point3D(200, 200, 500)); // lookAt start Point 
				break;
			}
		}
		
		private function setLowQuality():void 
		{
			if (qualityTimerId > -1) 
			{
				clearTimeout(qualityTimerId);
				qualityTimerId = -1;
			}
			//var precision:Number = 20;
			stage.quality = StageQuality.LOW;
			
		}
		
		private function startHighQualityTimer():void 
		{
			qualityTimerId = setTimeout(setHighQuality, qualitySwitchTime);
		}
		
		private function setHighQuality():void 
		{
			qualityTimerId = -1;
			stage.quality = StageQuality.HIGH;
			
		}
		
		private function loadNextResource():void
		{	
			loadingCounter++;
			
			if (loadingCounter < loadingSequence.length) {
				progressWindow.progress = (loadingCounter +1) / loadingSequence.length; 
				trace ("lala=" + progressWindow.progress + "");
				loadNextResource();
				//loadingSequence[loadingCounter].load(loadNextResource);
								
			} else {
				progressWindow.hide();
			}
		}
		
	}
}
